package com.wanyang.core.log.pattern;

import com.wanyang.util.SessionValidator;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.helpers.FormattingInfo;
import org.apache.log4j.helpers.PatternConverter;
import org.apache.log4j.helpers.PatternParser;
import org.apache.log4j.spi.LoggingEvent;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Map;

/**
 * Created by zhai on 15/12/24.
 */
public class HxzPatternParser extends PatternParser {


    public HxzPatternParser(String pattern) {
        super(pattern);
    }

    @Override
    protected void finalizeConverter(char c) {

        if (c == 'e') {
            PatternConverter pc = new HxzPatternConverter(formattingInfo, extractOption());
            currentLiteral.setLength(0);
            addConverter(pc);
        } else {
            super.finalizeConverter(c);
        }
    }

    static class HxzPatternConverter extends PatternConverter {

        private String optionFormat = null;

        protected HxzPatternConverter(FormattingInfo formattingInfo, String optionFormat) {
            super(formattingInfo);
            this.optionFormat = optionFormat;
        }

        @Override
        protected String convert(LoggingEvent event) {
            HttpServletRequest request = (HttpServletRequest) SessionValidator.getRequestContext();
            if (request == null) {
                return "";
            }
            HttpSession session = request.getSession();

            String buffer = optionFormat;

            final String remoteAddr = request.getRemoteAddr();
            buffer = StringUtils.replace(buffer, "%remoteAddr%", remoteAddr);

            final String method = request.getMethod();
            buffer = StringUtils.replace(buffer, "%method%", method);

            final String uri = request.getRequestURI();
            buffer = StringUtils.replace(buffer, "%uri%", uri != null ? uri : "");

            final String query = request.getQueryString();
            buffer = StringUtils.replace(buffer, "%query%", query != null ? ("?" + query) : "");

            final String params = getParameters(request);
            buffer = StringUtils.replace(buffer, "%parameters%", params != null ? params : "");

            String contents = "";
            if (StringUtils.isNotBlank(method) && method.equals("POST")) {
                Map<String, String[]> postParams = request.getParameterMap();
                String queryString = "";
                for (String key : postParams.keySet()) {
                    String[] values = postParams.get(key);
                    for (int i = 0; i < values.length; i++) {
                        String value = values[i];
                        queryString += key + "=" + value + "&";
                    }
                }
                contents = queryString;
            }
            buffer = StringUtils.replace(buffer, "%contents%", contents);

            String account = "server";
            buffer = StringUtils.replace(buffer, "%accountId%", account);
            return buffer;
        }

        private String getParameters(HttpServletRequest request) {
            Map<String, ?> parameterMap = request.getParameterMap();
            if (parameterMap != null) {
                StringBuilder param = new StringBuilder();

                for (Map.Entry<String, ?> entry : parameterMap.entrySet()) {

                    final String key = entry.getKey();

                    if (param.length() != 0) {
                        param.append(",");
                    }
                    param.append(key);
                    param.append("=");
                    Object val = entry.getValue();

                    if ("password".equalsIgnoreCase(key)) {
                        val = "********";
                    }

                    if (val instanceof String) {
                        param.append(val);
                    } else if (val instanceof String[]) {
                        String[] strArray = (String[]) val;
                        if (strArray.length > 1) {
                            param.append("(");
                        }
                        for (int i = 0; i < strArray.length; i++) {
                            if (i > 0) {
                                param.append(",");
                            }
                            param.append(strArray[i]);
                        }
                        if (strArray.length > 1) {
                            param.append(")");
                        }
                    } else {
                        param.append(entry.getValue());
                    }
                }
                return "{" + param.toString() + "}";
            }
            return null;
        }

    }
}
